package com.rtsapp.server.gamelog.analyze.stat.daily;

import com.rtsapp.server.gamelog.analyze.stat.DateUtils;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by admin on 16-7-27.
 */
public class DailyReportUtils {

    //需要计算的留存天
    private static final int[] retentionDays = new int[]{ 1, 2, 3,4,5,6,7,14,30};

    private final Date startDay;
    private final Date endDay;
    private final int startRegisterCount;
    private final Map<String, Set<Integer>> registerMap = new HashMap<>();
    private final Map<String, Set<Integer>> activeMap = new HashMap<>();
    private final Map<String, List<DataRecharge>> rechargeMap = new HashMap<>();

    public DailyReportUtils(Date startDay, Date endDay, int startRegisterCount, List<DataRegister> registerList, List<DataActive> activeList, List<DataRecharge> rechargeList) {
        this.startDay = startDay;
        this.endDay = endDay;
        this.startRegisterCount = startRegisterCount;


        {
            for( Date date = startDay; DateUtils.isDateBefore(date, endDay) ; date = DateUtils.increaseDate(date, 1) ){
                registerMap.put( convertDateToString( date ),  new HashSet<>() );
            }

            for (DataRegister register : registerList) {

                Set<Integer> registerIds = registerMap.get( convertDateToString(register.getLogTime()) );
                registerIds.add(register.getUserId());
            }
        }


        {
            for( Date date = startDay; DateUtils.isDateBefore(date, endDay) ; date = DateUtils.increaseDate(date, 1) ){
                activeMap.put( convertDateToString( date ),  new HashSet<>() );
            }

            for (DataActive active : activeList ) {

                String dateStr =  convertDateToString(active.getLogTime());

                Set<Integer> activeIds = activeMap.get( dateStr );
                if( activeIds == null ){
                    activeIds = new HashSet<>();
                    activeMap.put( dateStr , activeIds );
                }

                activeIds.add( active.getUserId());
            }
        }

        {
            for( Date date = startDay; DateUtils.isDateBefore(date, endDay) ; date = DateUtils.increaseDate(date, 1) ){
                rechargeMap.put( convertDateToString( date ),  new ArrayList<>() );
            }

            for (DataRecharge recharge : rechargeList) {
                rechargeMap.get( convertDateToString(recharge.getLogTime()) ).add(recharge);
            }

        }
    }


    public List<DailyReport> stat(){

        final List<DailyReport> reportList = new ArrayList<>();

        final Set<Integer> totalPayUserIds = new HashSet<>();
        final Set<Integer> registerPayUserIds = new HashSet<>();


        int totalRegister =  startRegisterCount;

        //循环计算每一天的报告
        for( Date date = startDay; DateUtils.isDateBefore(date, endDay) ; date = DateUtils.increaseDate(date, 1) ){

            DailyReport daily = new DailyReport( date );
            reportList.add( daily );

            String dateString = convertDateToString( date );

            //1. 注册人数, 总人数
            Set<Integer> registerIds = registerMap.get( dateString );
            int registerSize =  registerIds.size();
            totalRegister += registerSize;

            daily.setTotalRegister( totalRegister );
            daily.setDayRegister( registerSize );

            //2. DAU活跃人数
            daily.setDAU( activeMap.get( dateString ).size( ) );

            //3. 付费相关
            List<DataRecharge> rechargeList = rechargeMap.get( dateString );




            totalPayUserIds.clear();
            registerPayUserIds.clear();

            for( DataRecharge recharge : rechargeList ) {

                // 付费人数, 总金额
                totalPayUserIds.add(recharge.getUserId());
                daily.setTotalPayMoney( daily.getTotalPayMoney() + recharge.getMoney() );

                // 首充人数, 总金额
                if( recharge.getPayTimes() == 1 ){
                    daily.setFirstPayUser( daily.getFirstPayUser() + 1 );
                    daily.setFirstPayMoney( daily.getFirstPayMoney() + recharge.getMoney() );
                }

                // 注册付费人数, 总金额
                if( registerIds.contains( recharge.getUserId() ) ){
                    registerPayUserIds.add( recharge.getUserId() );
                    daily.setRegisterPayMoney( daily.getRegisterPayMoney() + recharge.getMoney() );
                }
            }


            daily.setTotalPayUser( totalPayUserIds.size() );
            daily.setRegisterPayUser(registerPayUserIds.size() );

            //4. 计算留存
            calculateRetention( daily );

        }

        return reportList;
    }


    private void calculateRetention(DailyReport daily) {

        Date date = daily.getDate();

        Date[] retentionDates = new Date[retentionDays.length];
        for( int i = 0 ; i < retentionDates.length; i++ ){
            retentionDates[ i ] =  DateUtils.increaseDate(date, retentionDays[i]);
        }

        Set<Integer> registerIds = registerMap.get( convertDateToString( date ) );

        int[] retentions = new int[ retentionDates.length ];
        for( int i = 0; i < retentionDates.length; i++ ){
            retentions[ i ] = containsSize( registerIds, activeMap.get( convertDateToString( retentionDates[i] ) ) );
        }


        daily.setRetentions(retentions);
    }


    /**
     * 第一个集合包含多少个第二个集合中的元素
     * @param registerIds
     * @param activeIds
     * @return
     */
    private static int containsSize( Set<Integer> registerIds, Set<Integer> activeIds ){
        if( activeIds == null || activeIds.size() < 1 ){
            return 0;
        }

        int totalSize = 0;
        for( Integer id : activeIds ){
            if( registerIds.contains( id ) ){
                totalSize++;
            }
        }

        return totalSize;
    }




    private static String convertDateToString( Date date ){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
        return sdf.format(date);
    }

    public static Set<String> getRetentionActiveDays(Date startDay, Date endDay) {
        Set<String> retentionDayStrs = new HashSet<>();

        for( Date date = startDay; DateUtils.isDateBefore(date, endDay) ; date = DateUtils.increaseDate(date, 1) ){

            //当前的
            retentionDayStrs.add(convertDateToString(date));

            //留存的
            for( int retentionDay : retentionDays ){
                String dateStr = convertDateToString( DateUtils.increaseDate(date, retentionDay) );
                retentionDayStrs.add( dateStr );
            }
        }

        return retentionDayStrs;
    }
}
